package uy.org.softtech.cssuite.jmx;

import static org.springframework.util.Assert.isTrue;
import static org.springframework.util.Assert.notNull;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;

import org.apache.log4j.Logger;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

/**
 * Clase que implementa {@link JMXAuthenticator} para proporcionar autenticación mediante Spring Security via JMX.
 * 
 * @author fabian.lobo
 */
@Component(value = "autenticator-jmx")
public class AutenticadorJmx implements JMXAuthenticator {
	
private Logger log = Logger.getLogger(getClass());
	
	@Resource(name = "gestor-autenticacion")
	private AuthenticationManager gestorAutenticacion;
		
	/**
	 * Método para verificar que todos los parámetros han sido seteados correctamente.
	 * 
	 * @author fabian.lobo
	 */
	@PostConstruct
	public void inicializacion(){
		notNull(gestorAutenticacion(), "La propiedad [gestorAutenticacion] de [" + getClass().getName() + "] no ha sido establecida.");
		
		log.info("Implementación para la autenticacion via JMX ha sido inicializado correctamente.");
	}

	@Override
	public Subject authenticate(Object credentials) {
		try {
			isTrue(credentials instanceof String[]);
			
			String[] info = (String[]) credentials;
			
			isTrue(info.length == 2);
			
			String usuario = info[0];
			String password = info[1];
			
			Authentication authentication = gestorAutenticacion().authenticate(new UsernamePasswordAuthenticationToken(usuario, password));
			Subject subject = new Subject();
			subject.getPrincipals().add(new JMXPrincipal(authentication.getName()));
			return subject;
		} catch (Throwable t) {
			log.error(t);
			throw new SecurityException();
		}
	}

	/*
	 *  GETTERS
	 */
	
	public AuthenticationManager gestorAutenticacion() {
		return gestorAutenticacion;
	}

}
